package net.matt2000.android.search.wp;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.provider.BaseColumns;

public class SuggestionProvider extends ContentProvider {

	private static final String ITEM = "Item";
	private static final String TEXT = "Text";
	private static final String DESCRIPTION = "Description";
	private static final String IMAGE = "Image";
	private static final String IMAGE_SOURCE = "source";

	@Override
	public int delete(Uri arg0, String arg1, String[] arg2) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean onCreate() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {

		String searchTerms = uri.getLastPathSegment();
		String language = uri.getPathSegments().get(0);
		int languageNumber = getLanguageNumber(getContext(), language);
		final MatrixCursor matrix = new MatrixCursor(
				new String[]{BaseColumns._ID, SearchManager.SUGGEST_COLUMN_ICON_1,
						SearchManager.SUGGEST_COLUMN_TEXT_1, SearchManager.SUGGEST_COLUMN_TEXT_2,
						SearchManager.SUGGEST_COLUMN_QUERY, SearchManager.SUGGEST_COLUMN_FLAGS});
		
		try {
			String query = URLEncoder.encode(searchTerms, "UTF-8");
	
			if (!getContext().getResources().obtainTypedArray(R.array.use_suggestions).getBoolean(languageNumber, false)) { //no suggestions
				String firstLine = getContext().getResources().getString(R.string.search_for)
					+ " '" + searchTerms +"'";
				String secondLine = getContext().getResources().getString(R.string.on)
					+ " " + getContext().getResources().getStringArray(R.array.website)[languageNumber];
				matrix.addRow(new Object[]{0, null, firstLine, secondLine, query});
				return matrix;
			}
	
			String urlString = getContext().getResources().getStringArray(R.array.suggestion_url)[languageNumber];
			urlString = urlString.replaceAll(Pattern.quote(getContext().getResources().getStringArray(R.array.search_term)[languageNumber]), query);
			
			URL url = new URL(urlString);
		    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		    DocumentBuilder builder = factory.newDocumentBuilder();
            Document dom = builder.parse(url.openStream());
            Element root = dom.getDocumentElement();
            NodeList items = root.getElementsByTagName(ITEM);
		    for (int i = 0; i<items.getLength(); i++) {
		    	Node item = items.item(i);
		    	NodeList properties = item.getChildNodes();
		    	String text = "";
		    	String description = "";
		    	String image = null;
		    	for (int j=0;j<properties.getLength();j++){
                    Node property = properties.item(j);
                    String name = property.getNodeName();
                    if (name.equals(TEXT)){
                        text = getTextContent(property);
                    } else if (name.equals(DESCRIPTION)){
                        description = getTextContent(property);
                        description = trimDescription(description, languageNumber); //remove the beginning of the description (for redundancy)
                    } else if (name.equals(IMAGE)){
                        String imageUrl = ((Element)property).getAttribute(IMAGE_SOURCE);
                        Uri.Builder b = new Uri.Builder();
                        b.scheme(ContentResolver.SCHEME_CONTENT);
                        b.authority(getContext().getResources().getString(R.string.icon_authority));
                        b.path(Uri.encode(imageUrl));
                        image = b.build().toString();
                    }
                }		    	
		    	matrix.addRow(new Object[]{i, image, text, description, text, SearchManager.FLAG_QUERY_REFINEMENT});
		    }

		} catch (ParserConfigurationException e) {
			// ignore
		} catch (MalformedURLException e) {
			// ignore
		} catch (SAXException e) {
			// ignore
		} catch (IOException e) {
			// ignore
		}

		return matrix;
		
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}
	
	private String trimDescription(String description, int languageNumber) {
		String firstSentence = description.split(getContext().getResources().getStringArray(R.array.end_of_sentence)[languageNumber])[0];
		CharSequence[] verbs = getContext().getResources().obtainTypedArray(R.array.verbs).getTextArray(languageNumber);
		String firstVerb = null;
		int firstPos = firstSentence.length();
		for (CharSequence verb : verbs) {
			int pos = firstSentence.indexOf(" "+verb+" ");
			if (pos>0 && pos<firstPos) {
				firstPos = pos;
				firstVerb = verb.toString();
			}
		}
		if (firstPos < firstSentence.length()) //at least one verb has been found
			return description.substring(firstSentence.indexOf(" "+firstVerb+" ")+1);
		else
			return description;

	}
	
	static String getTextContent(Node n) { //Node.getTextContent() is only available from API 8+
		switch (n.getNodeType()) {
			case Node.ELEMENT_NODE:
			case Node.ATTRIBUTE_NODE:
			case Node.ENTITY_NODE:
			case Node.ENTITY_REFERENCE_NODE:
			case Node.DOCUMENT_FRAGMENT_NODE:
				String t = "";
				NodeList nl = n.getChildNodes();
				for (int i = 0; i<nl.getLength(); i++) {
					if (nl.item(i).getNodeType()!=Node.COMMENT_NODE && nl.item(i).getNodeType()!=Node.PROCESSING_INSTRUCTION_NODE)
						t+=getTextContent(nl.item(i));
				}
				return t;
				
			case Node.TEXT_NODE:
			case Node.CDATA_SECTION_NODE:
			case Node.COMMENT_NODE:
			case Node.PROCESSING_INSTRUCTION_NODE:
				return n.getNodeValue();
				
			case Node.DOCUMENT_NODE:
			case Node.DOCUMENT_TYPE_NODE:
			case Node.NOTATION_NODE:
			default:
				return null;
		}
	}
	
	static int getLanguageNumber(Context context, String language) {
		String[] languages =context.getResources().getStringArray(R.array.language); 
		for (int i = 0; i < languages.length; i++) {
			if (languages[i].equals(language))
				return i;
		}
		return -1;
	}

	static int getLanguageNumber(Context context) {
		String className = context.getClass().getName();
		String[] languages =context.getResources().getStringArray(R.array.searchable_activity); 
		for (int i = 0; i < languages.length; i++) {
			if (languages[i].equalsIgnoreCase(className))
				return i;
		}
		return -1;
	}
}
